package com.yilin.tms.core.components.interceptor;


import com.google.gson.reflect.TypeToken;
import com.yilin.commons.util.JsonUtil;
import com.yilin.tms.core.commons.constant.HttpConstant;
import com.yilin.tms.core.application.ServiceUtil;
import com.yilin.tms.core.commons.annotation.NoLoginSecurity;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import feign.Util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.*;

import static java.nio.charset.StandardCharsets.*;

/***
 * 微服务转发拦截器
 * */
@Configuration
public class ReqProviderInterceptor implements RequestInterceptor {

    private Logger logger = LoggerFactory.getLogger(ReqProviderInterceptor.class);
    @Value("XXX")
    private String roboitToKen ;

    @Override
    public void apply(RequestTemplate requestTemplate) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        requestTemplate.header(HttpConstant.PROVIDER_SERVICE, new Date().toString());
        requestTemplate.header(HttpConstant.GATEWAY_ZUUL, "0");
        Method method = requestTemplate.methodMetadata().method();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            //处理转发微服务之间的头部
            Enumeration<String> headerNames = request.getHeaderNames();
            if (headerNames != null) {
                while (headerNames.hasMoreElements()) {
                    String name = headerNames.nextElement();
                    String values = request.getHeader(name);
                    requestTemplate.header(name, values);
                }
            }
            //为了微服务间通讯安全，添加这个注解必须注入安全头
//            if (request.getHeader("token") == null) {
//                String safeKey = ServiceUtil.saveServiceSafeNotify(method.getName());
//                requestTemplate.header(HttpConstant.SERVICE_SAFE_KEY, safeKey);
//            }
        }else{
//            requestTemplate.header(HttpConstant.TOKEN, roboitToKen);
//            内部任务通道
            String safeKey = ServiceUtil.saveServiceSafeNotify(method.getName());
            requestTemplate.header(HttpConstant.SERVICE_SAFE_KEY, safeKey);
        }
        //使用下面的方法将数据参数转为数据流，优点，数据过大时不会中断
        Map<String, Object> bodyAllMap = new HashMap<>();
        try {
            //处理RequestParam
            Map<String, Collection<String>> queries = requestTemplate.queries();
            for (Map.Entry<String, Collection<String>> entry : queries.entrySet()) {
                Collection<String> pram = entry.getValue();
                if (!pram.isEmpty()) {
                    String entryData = URLDecoder.decode((String) ((List) pram).get(0), "UTF-8");
                    bodyAllMap.put(entry.getKey(), entryData);
                }
            }
            requestTemplate.queries(null);
            //处理请求body
            byte[] data = requestTemplate.body();
            if (data != null && data.length > 0) {
                String bodyJson = new String(data, UTF_8);
                Map<String, Object> bodyMap = JsonUtil.jsonToObject(bodyJson, new TypeToken<Map<String, Object>>() {
                });
                bodyAllMap.putAll(bodyMap);
            }
        } catch (Exception e) {
            logger.error("FeignClient Request Body Error !", e);
        } finally {
            requestTemplate.header("Content-Type", "application/json;charset=UTF-8");
            String jsonString = JsonUtil.objectToJson(bodyAllMap);
            byte[] bodyData = jsonString.getBytes(Util.UTF_8);// 替换请求体
            requestTemplate.body(bodyData, Util.UTF_8);
        }
    }
}
